//go:build wasm
// +build wasm

package wasm

import (
	"fmt"
	"syscall/js"
)

// WasmInstance WebAssembly实例
type WasmInstance struct {
	exports map[string]js.Value
	memory  js.Value
}

// WasmRuntime WebAssembly运行时
type WasmRuntime struct {
	instances map[string]*WasmInstance
}

func NewWasmRuntime() (*WasmRuntime, error) {
	return &WasmRuntime{
		instances: make(map[string]*WasmInstance),
	}, nil
}

func (r *WasmRuntime) LoadModule(name string, wasmBytes []byte) error {
	global := js.Global()

	wasmInstance := &WasmInstance{
		exports: make(map[string]js.Value),
	}

	uint8Array := js.Global().Get("Uint8Array").New(len(wasmBytes))
	js.CopyBytesToJS(uint8Array, wasmBytes)

	promise := global.Get("WebAssembly").Call("instantiate", uint8Array)
	instance := promise.Get("instance")

	exports := instance.Get("exports")
	wasmInstance.memory = exports.Get("memory")

	exportNames := js.Global().Get("Object").Call("keys", exports)
	for i := 0; i < exportNames.Length(); i++ {
		name := exportNames.Index(i).String()
		wasmInstance.exports[name] = exports.Get(name)
	}

	r.instances[name] = wasmInstance
	return nil
}

func (r *WasmRuntime) CallFunction(moduleName, functionName string, args ...interface{}) (interface{}, error) {
	instance, ok := r.instances[moduleName]
	if !ok {
		return nil, fmt.Errorf("module %s not found", moduleName)
	}

	fn, ok := instance.exports[functionName]
	if !ok {
		return nil, fmt.Errorf("function %s not found in module %s", functionName, moduleName)
	}

	jsArgs := make([]interface{}, len(args))
	for i, arg := range args {
		jsArgs[i] = js.ValueOf(arg)
	}

	result := fn.Invoke(jsArgs...)
	return result.Float(), nil // 修改为返回float64值，因为js.Value没有Interface()方法
}

func (r *WasmRuntime) Close() error {
	r.instances = make(map[string]*WasmInstance)
	return nil
}
